﻿using AutoMapper;
using Medical.Api.Read.Application.Command.Wms.WmsStoresCommand;
using Medical.Api.Read.Dto.WmsDto;
using Medical.Api.Read.Dto.WmsDto.WmsLssueDto;
using Medical.Api.Read.Dto.WmsDto.WmsOutDto;
using Medical.Api.Read.Dto.WmsDto.WmsStorageDto;
using Medical.Api.Read.Dto.WmsDto.WmsStoresDro;
using Medical.Domain.BasicManagement;
using Medical.Domain.Enum;
using Medical.Domain.RBAC;
using Medical.Domain.Wms;
using Medical.ErrorCode;
using Medical.Interstructrue.Base;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using static Medical.Domain.Enum.DepartmentEnum;

namespace Medical.Api.Read.Service.WmsService
{
    /// <summary>
    /// WMS（仓储管理）服务实现，负责出库、存放、物品等相关业务逻辑。
    /// </summary>
    public class WmsService : IWmsService
    {
        /// <summary>
        /// 入库主表仓储
        /// </summary>
        private readonly IBaseRepository<WmsStorage> _storageRepository;
        /// <summary>
        /// 存放表仓储
        /// </summary>
        private readonly IBaseRepository<WmsStores> _storesRepository;
        /// <summary>
        /// 货架表仓储
        /// </summary>
        private readonly IBaseRepository<Shelves> _shelvesRepository;
        /// <summary>
        /// 器械表仓储
        /// </summary>
        private readonly IBaseRepository<Apparatus> _apparatusRepository;
        /// <summary>
        /// 器械包表仓储
        /// </summary>
        private readonly IBaseRepository<EquipmentPackage> _equipmentPackageRepository;
        /// <summary>
        /// 出库主表仓储
        /// </summary>
        private readonly IBaseRepository<WmsOut> _outRepository;
        /// <summary>
        /// 出库明细表仓储
        /// </summary>
        private readonly IBaseRepository<WmsOutDetail> _outDetailRepository;
        private readonly IBaseRepository<WmsLssue> _lssueRepository;
        private readonly IBaseRepository<WmsLssueDetail> _lssueDetailRepository;
        /// <summary>
        /// AutoMapper实例
        /// </summary>
        private readonly IMapper _mapper;
        /// <summary>
        /// 日志
        /// </summary>
        private readonly ILogger<WmsService> _wms;

        /// <summary>
        /// 构造函数，注入所有仓储、映射和日志依赖
        /// </summary>
        public WmsService(
            IBaseRepository<WmsStorage> storageRepository,
            IBaseRepository<WmsStores> storesRepository,
            IBaseRepository<Shelves> shelvesRepository,
            IBaseRepository<Apparatus> apparatusRepository,
            IBaseRepository<EquipmentPackage> equipmentPackageRepository,
            IBaseRepository<WmsOut> outRepository,
            IBaseRepository<WmsOutDetail> outDetailRepository,
            IBaseRepository<WmsLssue> lssueRepository,
            IBaseRepository<WmsLssueDetail> lssueDetailRepository,
            IMapper mapper,
            ILogger<WmsService> wms)
        {
            _storageRepository = storageRepository;
            _storesRepository = storesRepository;
            _shelvesRepository = shelvesRepository;
            _apparatusRepository = apparatusRepository;
            _equipmentPackageRepository = equipmentPackageRepository;
            _outRepository = outRepository;
            _outDetailRepository = outDetailRepository;
            _lssueRepository = lssueRepository;
            _lssueDetailRepository = lssueDetailRepository;
            _mapper = mapper;
            _wms = wms;
        }

        /// <summary>
        /// 获取指定货架的所有存放信息（按层号和格数补全空位）
        /// </summary>
        /// <param name="dto">查询参数</param>
        /// <returns>存放信息列表</returns>
        public async Task<ApiResult<List<WmsStoresPageDto>>> GetStoresListAsync(QueryStoresDto dto)
        {
            var shelf = _shelvesRepository.GetModel(dto.ShelfId);
            if (shelf == null)
            {
                return new ApiResult<List<WmsStoresPageDto>>
                {
                    Code = ApiEnums.Fail,
                    Msg = "货架不存在",
                    Data = null
                };
            }
            var stores = _storesRepository.GetAll().Where(x => x.ShelfId == dto.ShelfId).ToList();
            var result = new List<WmsStoresPageDto>();
            for (int floor = 1; floor <= shelf.Layers; floor++)
            {
                for (int grid = 1; grid <= shelf.Grids; grid++)
                {
                    var store = stores.FirstOrDefault(x => x.FloorNum == floor && x.LatticeNum == grid);
                    if (store != null)
                    {
                        var dtoItem = _mapper.Map<WmsStoresPageDto>(store);
                        // 物品名称补全
                        if (store.MaterialType == Medical.Domain.Enum.MaterialTypeEnum.Instrument)
                        {
                            var apparatus = _apparatusRepository.GetModel(store.MaterialId);
                            dtoItem.MaterialName = apparatus?.ApparatusName ?? string.Empty;
                        }
                        else if (store.MaterialType == Medical.Domain.Enum.MaterialTypeEnum.器械包)
                        {
                            var pack = _equipmentPackageRepository.GetModel(store.MaterialId);
                            dtoItem.MaterialName = pack?.PackageName ?? string.Empty;
                        }
                        result.Add(dtoItem);
                    }
                    else
                    {
                        result.Add(new WmsStoresPageDto
                        {
                            ShelfId = dto.ShelfId,
                            FloorNum = floor,
                            LatticeNum = grid,
                            StoresNum = 0,
                            StoresState = false,
                            MaterialName = string.Empty,
                            MaterialTypeName = string.Empty
                        });
                    }
                }
            }
            return new ApiResult<List<WmsStoresPageDto>>
            {
                Code = ApiEnums.Success,
                Data = result
            };
        }

        /// <summary>
        /// 获取所有待存放物品（StoresState=false）
        /// </summary>
        /// <returns>待存放物品列表</returns>
        public async Task<List<WaitStoreDto>> GetWaitStoresListAsync()
        {
            var waitStores = _storesRepository.GetAll().Where(x => !x.StoresState).ToList();
            var result = new List<WaitStoreDto>();
            foreach (var store in waitStores)
            {
                var dto = new WaitStoreDto
                {
                    Id = store.Id,
                    MaterialTypeName = store.MaterialType.ToString(),
                    MaterialName = string.Empty,
                    StoresNum = store.StoresNum
                };
                if (store.MaterialType == Medical.Domain.Enum.MaterialTypeEnum.Instrument)
                {
                    var apparatus = _apparatusRepository.GetModel(store.MaterialId);
                    dto.MaterialName = apparatus?.ApparatusName ?? string.Empty;
                }
                else if (store.MaterialType == Medical.Domain.Enum.MaterialTypeEnum.器械包)
                {
                    var pack = _equipmentPackageRepository.GetModel(store.MaterialId);
                    dto.MaterialName = pack?.PackageName ?? string.Empty;
                }
                result.Add(dto);
            }
            return await Task.FromResult(result);
        }

        /// <summary>
        /// 根据物品id和类型获取物品详情（器械/器械包）
        /// </summary>
        /// <param name="id">物品id</param>
        /// <param name="materialType">物品类型</param>
        /// <returns>物品详情</returns>
        public async Task<MaterialDetailDto> GetMaterialByIdAsync(int id, int materialType)
        {
            var result = new MaterialDetailDto();
            if (materialType == (int)Medical.Domain.Enum.MaterialTypeEnum.Instrument)
            {
                var apparatus = _apparatusRepository.GetModel(id);
                if (apparatus != null)
                {
                    result.Id = apparatus.Id;
                    result.MaterialName = apparatus.ApparatusName;
                    result.MaterialTypeName = Medical.Domain.Enum.MaterialTypeEnum.Instrument.ToString();
                    result.Price = apparatus.Price;
                }
            }
            else if (materialType == (int)Medical.Domain.Enum.MaterialTypeEnum.器械包)
            {
                var pack = _equipmentPackageRepository.GetModel(id);
                if (pack != null)
                {
                    result.Id = pack.Id;
                    result.MaterialName = pack.PackageName;
                    result.MaterialTypeName = Medical.Domain.Enum.MaterialTypeEnum.器械包.ToString();
                    result.Price = pack.ServicePrice;
                }
            }
            return await Task.FromResult(result);
        }

        /// <summary>
        /// 根据出库单id获取出库详情及明细
        /// </summary>
        /// <param name="id">出库单id</param>
        /// <returns>出库详情及明细</returns>
        public async Task<ApiResult<WmsOutDetailReadDto>> GetOutCauseDetailByIdAsync(int id)
        {
            var outEntity = _outRepository.GetModel(id);
            if (outEntity == null)
            {
                return new ApiResult<WmsOutDetailReadDto> { Code = ApiEnums.Fail, Msg = "出库单不存在", Data = null };
            }
            var details = _outDetailRepository.GetAll().Where(x => x.OutId == id).ToList();
            var dto = new WmsOutDetailReadDto
            {
                Id = outEntity.Id,
                OutCode = outEntity.OutCode,
                OutWarehouse = (WarehouseEnum)(int)outEntity.OutWarehouse,
                OutWarehouseName = outEntity.OutWarehouse.ToString(),
                OutReason = (OutCauseEnum)(int)outEntity.OutReason,
                OutReasonName = outEntity.OutReason.ToString(),
                AuditState = (ApprovalStateEnum)(int)outEntity.AuditState,
                AuditStateName = outEntity.AuditState.ToString(),
                AuditName = outEntity.AuditName,
                AuditDate = outEntity.AuditDate,
                CreateTime = outEntity.CreateTime,
                Details = details.Select(d => new WmsOutDetailItemReadDto
                {
                    Id = d.Id,
                    MaterialId = d.MaterialId,
                    MaterialType = (MaterialTypeEnum)(int)d.MaterialType,
                    MaterialTypeNmae = d.MaterialType.ToString(),
                    MaterialCode = d.MaterialCode,
                    MaterialName = d.MaterialName,
                    OutNum = d.OutNum
                }).ToList()
            };
            return await Task.FromResult(new ApiResult<WmsOutDetailReadDto>
            {
                Code = ApiEnums.Success,
                Data = dto
            });
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="queryDto"></param>
        /// <returns></returns>
        public async Task<ApiResult<ApiPageIng<WmsLssuePageDto>>> GetLssueByPageAsync(WmsLssueQueryDto queryDto)
        {
            // 构建基础查询（未删除）
            var query = _lssueRepository.GetAll().Where(x => !x.IsDeleted);

            // 按发放时间筛选
            if (queryDto.StartTime.HasValue)
                query = query.Where(x => x.CreateTime >= queryDto.StartTime.Value);
            if (queryDto.EndTime.HasValue)
                query = query.Where(x => x.CreateTime <= queryDto.EndTime.Value);

            // LssueState为空查0和5，否则严格按条件查
            if (!queryDto.LssueState.HasValue)
            {
                query = query.Where(x => (int)x.LssueState == 0 || (int)x.LssueState == 5);
            }
            else
            {
                query = query.Where(x => (int)x.LssueState == queryDto.LssueState.Value);
            }

            // 按发放单号筛选
            if (!string.IsNullOrEmpty(queryDto.LssueCode))
                query = query.Where(x => x.LssueCode.Contains(queryDto.LssueCode));

            // 按发放人筛选
            if (!string.IsNullOrEmpty(queryDto.LssueName))
                query = query.Where(x => x.LssueName.Contains(queryDto.LssueName));


            // 按接收人筛选
            if (!string.IsNullOrEmpty(queryDto.AcceptName))
                query = query.Where(x => x.AcceptName.Contains(queryDto.AcceptName));

            // 总数
            var total = query.Count();

            // 分页并投影为DTO
            var pageData = query
                .OrderByDescending(x => x.LssueDate)
                .Skip((queryDto.PageIndex - 1) * queryDto.PageSize)
                .Take(queryDto.PageSize)
                .Select(x => new WmsLssuePageDto
                {
                    Id = x.Id,
                    LssueCode = x.LssueCode,
                    LssueName = x.LssueName,
                    LssueDate = x.LssueDate,
                    //DepaId = x.DepaId,
                    ApplyingUnit = x.ApplyingUnit,
                    ApplyingUnitNmae = x.ApplyingUnit.ToString(),
                    AcceptName = x.AcceptName,
                    LssueState = (int)x.LssueState,
                    LssueStateName = x.LssueState.ToString(),
                    CreateTime = x.CreateTime
                })
                .ToList();

            // 组装分页结果
            var result = new ApiPageIng<WmsLssuePageDto>
            {
                PageData = pageData,
                TotalCount = total,
                PageIndex = queryDto.PageIndex,
                PageSize = queryDto.PageSize
            };

            return await Task.FromResult(new ApiResult<ApiPageIng<WmsLssuePageDto>>
            {
                Code = ApiEnums.Success,
                Data = result
            });
        }

        public async Task<ApiResult<WmsLssueDetailReadDto>> GetLssueDetailByIdAsync(int id)
        {
            var entity = _lssueRepository.GetModel(id);
            if (entity == null)
            {
                return new ApiResult<WmsLssueDetailReadDto> { Code = ApiEnums.Fail, Msg = "发放单不存在", Data = null };
            }
            // 获取明细
            var details = _lssueDetailRepository.GetAll().Where(x => x.LssueId == id).ToList();
            var dto = new WmsLssueDetailReadDto
            {
                Id = entity.Id,
                LssueCode = entity.LssueCode,
                LssueName = entity.LssueName,
                LssueDate = entity.LssueDate,
                //DepaId = entity.DepaId,
                ApplyingUnit = entity.ApplyingUnit,
                AcceptName = entity.AcceptName,
                LssueState = (int)entity.LssueState,
                LssueStateName = entity.LssueState.ToString(),
                Details = details.Select(d => new WmsLssueDetailItemReadDto
                {
                    Id = d.Id,
                    MaterialType = (int)d.MaterialType,
                    MaterialTypeName = d.MaterialType.ToString(),
                    MaterialId = d.MaterialId,
                    MaterialCode = d.MaterialCode,
                    MaterialName = d.MaterialName,
                    LssueNum = d.LssueNum
                }).ToList()
            };
            return await Task.FromResult(new ApiResult<WmsLssueDetailReadDto>
            {
                Code = ApiEnums.Success,
                Data = dto
            });
        }

        /// <summary>
        /// 获取已审批的入库主表列表
        /// </summary>
        public async Task<List<WmsStoragePageDto>> GetApprovedStorageListAsync()
        {
            var list = _storageRepository.GetAll()
                .Where(x => x.AuditState == true && !x.IsDeleted)
                .OrderByDescending(x => x.CreateTime)
                .Select(x => new WmsStoragePageDto
                {
                    Id = x.Id,
                    StorageCode = x.StorageCode,
                    StorageType = (int)x.StorageType,
                    StorageTypeName = x.StorageType.ToString(),
                    Warehouse = (int)x.Warehouse,
                    WarehouseName = x.Warehouse.ToString(),
                    Supplier = (int)x.Supplier,
                    SupplierName = x.Supplier.ToString(),
                    StorageExplain = x.StorageExplain,
                    AuditState = x.AuditState,
                    AuditName = x.AuditName,
                    AuditDate = x.AuditDate,
                    CreateTime = x.CreateTime
                })
                .ToList();
            return await Task.FromResult(list);
        }

        /// <summary>
        /// 获取已审批的出库主表列表
        /// </summary>
        public async Task<List<WmsOutPageDto>> GetApprovedOutListAsync()
        {
            var list = _outRepository.GetAll()
                .Where(x => (int)x.AuditState == 5 && !x.IsDeleted)
                .OrderByDescending(x => x.CreateTime)
                .Select(x => new WmsOutPageDto
                {
                    Id = x.Id,
                    OutCode = x.OutCode,
                    OutWarehouse = (WarehouseEnum)(int)x.OutWarehouse,
                    OutWarehouseName = x.OutWarehouse.ToString(),
                    OutReason = (OutCauseEnum)(int)x.OutReason,
                    OutReasonName = x.OutReason.ToString(),
                    ApplyingUnitName = x.ApplyingUnit.ToString(),
                    AuditState = (ApprovalStateEnum)(int)x.AuditState,
                    AuditStateName = x.AuditState.ToString(),
                    ApplyingUnit = (ApplyingUnitEnum)x.ApplyingUnit,
                    AuditName = x.AuditName,
                    AuditDate = x.AuditDate,
                    CreateTime = x.CreateTime
                })
                .ToList();
            return await Task.FromResult(list);
        }

    }
}
